//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ReShade effect file
// visit facebook.com/MartyMcModding for news/updates
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Heat Haze Effect by robi29
// Copyright © 2015-2016 robi29
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

#define EXTRASUNNY_HEATHAZE 	0.9
#define CLEAR_HEATHAZE 			0.8
#define NEUTRAL_HEATHAZE 		1.0
#define SMOG_HEATHAZE			0.5
#define FOGGY_HEATHAZE			0.0
#define OVERCAST_HEATHAZE		0.0
#define CLOUDS_HEATHAZE			0.2
#define CLEARING_HEATHAZE		0.0
#define RAIN_HEATHAZE			0.0
#define THUNDER_HEATHAZE		0.0
#define SNOW_HEATHAZE			0.0
#define BLIZZARD_HEATHAZE		0.0
#define LIGHTSNOW_HEATHAZE		0.0
#define XMAS_HEATHAZE			0.0
#define NULL_HEATHAZE			0.0

#define H0			0.0
#define H1			0.0
#define H2			0.0
#define H3			0.0
#define H4			0.0
#define H5			0.0
#define H6			0.0
#define H7			0.0
#define H8			0.0
#define H9			0.0
#define H10			0.5
#define H11			1.0
#define H12			1.0
#define H13			1.0
#define H14			1.0
#define H15			1.0
#define H16			1.0
#define H17			1.0
#define H18			0.7
#define H19			0.3
#define H20			0.0
#define H21			0.0
#define H22			0.0
#define H23			0.0

texture2D texBlur0 		{ Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
texture2D texBlur1 		{ Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
texture2D texBlur2 		{ Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };

texture2D texHeatHaze  <string source = "ReShade/heathaze.png";> { Width = 200; Height = 200; Format = R8;};

sampler2D SamplerBlur0
{
	Texture = texBlur0;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};

sampler2D SamplerBlur1
{
	Texture = texBlur1;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};

sampler2D SamplerBlur2
{
	Texture = texBlur2;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};

sampler2D SamplerHeatHaze
{
	Texture = texHeatHaze;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Wrap;
	AddressV = Wrap;
};

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

float ComputeFadeOutHeatHaze()
{
	float3 fadeOutTex = tex2D(SamplerColor, float2(0.0, 0.0)).rgb;
	[flatten]
	if (fadeOutTex.b < 1.0)
	{
		return 0.0f;
	}
	
	int R = fadeOutTex.r * 255;
	
	int w0 = (R & 0x000000F0) >> 4;
	int w1 = R & 0x0000000F;
	
	static const float weathers[15] = {
		EXTRASUNNY_HEATHAZE,
		CLEAR_HEATHAZE,
		CLOUDS_HEATHAZE,
		SMOG_HEATHAZE,
		FOGGY_HEATHAZE,
		OVERCAST_HEATHAZE,
		RAIN_HEATHAZE,
		THUNDER_HEATHAZE,
		CLEARING_HEATHAZE,
		NEUTRAL_HEATHAZE,
		SNOW_HEATHAZE,
		BLIZZARD_HEATHAZE,
		LIGHTSNOW_HEATHAZE,
		XMAS_HEATHAZE,
		NULL_HEATHAZE
	};
	
	static const float hours[25] = {
		H0,
		H1,
		H2,
		H3,
		H4,
		H5,
		H6,
		H7,
		H8,
		H9,
		H10,
		H11,
		H12,
		H13,
		H14,
		H15,
		H16,
		H17,
		H18,
		H19,
		H20,
		H21,
		H22,
		H23,
		H0
	};
	
	float3 timeTex = tex2D(SamplerColor, float2(1.0, 0.0)).rgb;
	
	float hour = timeTex.r*255.0 + timeTex.g*255.0/60.0 + timeTex.b*255.0/3600.0;
	
	return float(lerp(hours[int(hour)], hours[(int(hour)+1)], timeTex.g*255.0/60.0) * lerp(weathers[w0], weathers[w1], fadeOutTex.g));
}

float GetCameraAngle()
{
	float angle = tex2D(SamplerColor, float2(0.0, 1.0)).r;
	angle -= 0.25;
	angle *= 5.0;
	angle -= 0.1;
	return angle;
}

float GetHeight()
{
	float angle = tex2D(SamplerColor, float2(0.0, 1.0)).g;
	return angle;
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void PS_Blur0(float4 vpos : SV_Position, float2 texcoord : TEXCOORD, out float4 color : SV_Target0) 
{
	color = tex2D(SamplerColor, texcoord);
	if (texcoord.x < PixelSize.x && texcoord.y < PixelSize.y)
	{
		color = tex2D(SamplerColor, float2(PixelSize.x*2.0f, PixelSize.y));
	}
	else if (texcoord.x > 1.0f-PixelSize.x && texcoord.y < PixelSize.y)
	{
		color = tex2D(SamplerColor, float2(1.0f-PixelSize.x*2.0f, PixelSize.y));
	}
	else if (texcoord.x < PixelSize.x && texcoord.y > 1.0f-PixelSize.y)
	{
		color = tex2D(SamplerColor, float2(PixelSize.x, 1.0f-PixelSize.y*2.0f));
	}
}

void PS_Blur1(float4 vpos : SV_Position, float2 texcoord : TEXCOORD, out float4 color : SV_Target0)
{
	float fadeOut = ComputeFadeOutHeatHaze();
	static float2 blurTexCoords[14];
		
	blurTexCoords[ 0] = texcoord + float2(0.0, -7.0*BUFFER_RCP_HEIGHT);
	blurTexCoords[ 1] = texcoord + float2(0.0, -6.0*BUFFER_RCP_HEIGHT);
	blurTexCoords[ 2] = texcoord + float2(0.0, -5.0*BUFFER_RCP_HEIGHT);
	blurTexCoords[ 3] = texcoord + float2(0.0, -4.0*BUFFER_RCP_HEIGHT);
	blurTexCoords[ 4] = texcoord + float2(0.0, -3.0*BUFFER_RCP_HEIGHT);
	blurTexCoords[ 5] = texcoord + float2(0.0, -2.0*BUFFER_RCP_HEIGHT);
	blurTexCoords[ 6] = texcoord + float2(0.0, -1.0*BUFFER_RCP_HEIGHT);
	blurTexCoords[ 7] = texcoord + float2(0.0,  1.0*BUFFER_RCP_HEIGHT);
	blurTexCoords[ 8] = texcoord + float2(0.0,  2.0*BUFFER_RCP_HEIGHT);
	blurTexCoords[ 9] = texcoord + float2(0.0,  3.0*BUFFER_RCP_HEIGHT);
	blurTexCoords[10] = texcoord + float2(0.0,  4.0*BUFFER_RCP_HEIGHT);
	blurTexCoords[11] = texcoord + float2(0.0,  5.0*BUFFER_RCP_HEIGHT);
	blurTexCoords[12] = texcoord + float2(0.0,  6.0*BUFFER_RCP_HEIGHT);
	blurTexCoords[13] = texcoord + float2(0.0,  7.0*BUFFER_RCP_HEIGHT);
		
	//float heatup = tex2D(SamplerHeatHaze, (texcoord * float2(BUFFER_WIDTH,BUFFER_HEIGHT) * 0.01)+float2(0.0,Timer.x*0.0002)).g;
	//float heatdown = tex2D(SamplerHeatHaze, (texcoord * float2(BUFFER_WIDTH,BUFFER_HEIGHT) * 0.01)+float2(0.0,Timer.x*0.0002)).r;
		
	color = 0.0;
	
	float angle = GetCameraAngle();
		
	if (fadeOut > 0.0 && angle < texcoord.y)
	{
		color += tex2D(SamplerBlur0, blurTexCoords[ 0])*0.0044299121055113265;
		color += tex2D(SamplerBlur0, blurTexCoords[ 1])*0.00895781211794;
		color += tex2D(SamplerBlur0, blurTexCoords[ 2])*0.0215963866053;
		color += tex2D(SamplerBlur0, blurTexCoords[ 3])*0.0443683338718;
		color += tex2D(SamplerBlur0, blurTexCoords[ 4])*0.0776744219933;
		color += tex2D(SamplerBlur0, blurTexCoords[ 5])*0.115876621105;
		color += tex2D(SamplerBlur0, blurTexCoords[ 6])*0.147308056121;
		color += tex2D(SamplerBlur0, texcoord         )*0.159576912161;
		color += tex2D(SamplerBlur0, blurTexCoords[ 7])*0.147308056121;
		color += tex2D(SamplerBlur0, blurTexCoords[ 8])*0.115876621105;
		color += tex2D(SamplerBlur0, blurTexCoords[ 9])*0.0776744219933;
		color += tex2D(SamplerBlur0, blurTexCoords[10])*0.0443683338718;
		color += tex2D(SamplerBlur0, blurTexCoords[11])*0.0215963866053;
		color += tex2D(SamplerBlur0, blurTexCoords[12])*0.00895781211794;
		color += tex2D(SamplerBlur0, blurTexCoords[13])*0.0044299121055113265;
			
		float angle2 = abs(texcoord.y - angle);
		angle2 *= 10.0;
		if (angle2 > 1.0)
		{
			angle2 = 1.0;
		}
		
		float multiply = 1.2*angle2*fadeOut*GetHeight();
		float distance = GetLinearDepth(texcoord);
		if (distance > 0.7) {}
		else if (distance > 0.4)
		{
			distance -= 0.4;
			distance *= 10.0/3.0;
			multiply *= distance;
		}
		else
		{
			multiply = 0.0;
		}
		color *= multiply;
		color += tex2D(SamplerBlur0, texcoord)*(1.0-multiply); 
	}
	else
	{
		color = tex2D(SamplerBlur0, texcoord);
	}
}

void PS_Blur2(float4 vpos : SV_Position, float2 texcoord : TEXCOORD, out float4 color : SV_Target0)
{
	float fadeOut = ComputeFadeOutHeatHaze();
	static float2 blurTexCoords[14];
		
	blurTexCoords[ 0] = texcoord + float2(-7.0*BUFFER_RCP_WIDTH, 0.0);
	blurTexCoords[ 1] = texcoord + float2(-6.0*BUFFER_RCP_WIDTH, 0.0);
	blurTexCoords[ 2] = texcoord + float2(-5.0*BUFFER_RCP_WIDTH, 0.0);
	blurTexCoords[ 3] = texcoord + float2(-4.0*BUFFER_RCP_WIDTH, 0.0);
	blurTexCoords[ 4] = texcoord + float2(-3.0*BUFFER_RCP_WIDTH, 0.0);
	blurTexCoords[ 5] = texcoord + float2(-2.0*BUFFER_RCP_WIDTH, 0.0);
	blurTexCoords[ 6] = texcoord + float2(-1.0*BUFFER_RCP_WIDTH, 0.0);
	blurTexCoords[ 7] = texcoord + float2(1.0*BUFFER_RCP_WIDTH, 0.0);
	blurTexCoords[ 8] = texcoord + float2(2.0*BUFFER_RCP_WIDTH, 0.0);
	blurTexCoords[ 9] = texcoord + float2(3.0*BUFFER_RCP_WIDTH, 0.0);
	blurTexCoords[10] = texcoord + float2(4.0*BUFFER_RCP_WIDTH, 0.0);
	blurTexCoords[11] = texcoord + float2(5.0*BUFFER_RCP_WIDTH, 0.0);
	blurTexCoords[12] = texcoord + float2(6.0*BUFFER_RCP_WIDTH, 0.0);
	blurTexCoords[13] = texcoord + float2(7.0*BUFFER_RCP_WIDTH, 0.0);
		
	color = 0.0;
	
	static float offset = (Timer % 1000);
		
	//float heatup = tex2D(SamplerHeatHaze, (texcoord * float2(BUFFER_WIDTH,BUFFER_HEIGHT) * 0.01)+float2(0.0,Timer.x*0.0002)).g;
	//float heatdown = tex2D(SamplerHeatHaze, (texcoord * float2(BUFFER_WIDTH,BUFFER_HEIGHT) * 0.01)+float2(0.0,Timer.x*0.0002)).r;
	
	
	float angle = GetCameraAngle();
		
	if (fadeOut > 0.0 && angle < texcoord.y)
	{
		color += tex2D(SamplerBlur1, blurTexCoords[ 0])*0.0044299121055113265;
		color += tex2D(SamplerBlur1, blurTexCoords[ 1])*0.00895781211794;
		color += tex2D(SamplerBlur1, blurTexCoords[ 2])*0.0215963866053;
		color += tex2D(SamplerBlur1, blurTexCoords[ 3])*0.0443683338718;
		color += tex2D(SamplerBlur1, blurTexCoords[ 4])*0.0776744219933;
		color += tex2D(SamplerBlur1, blurTexCoords[ 5])*0.115876621105;
		color += tex2D(SamplerBlur1, blurTexCoords[ 6])*0.147308056121;
		color += tex2D(SamplerBlur1, texcoord         )*0.159576912161;
		color += tex2D(SamplerBlur1, blurTexCoords[ 7])*0.147308056121;
		color += tex2D(SamplerBlur1, blurTexCoords[ 8])*0.115876621105;
		color += tex2D(SamplerBlur1, blurTexCoords[ 9])*0.0776744219933;
		color += tex2D(SamplerBlur1, blurTexCoords[10])*0.0443683338718;
		color += tex2D(SamplerBlur1, blurTexCoords[11])*0.0215963866053;
		color += tex2D(SamplerBlur1, blurTexCoords[12])*0.00895781211794;
		color += tex2D(SamplerBlur1, blurTexCoords[13])*0.0044299121055113265;
			
		float angle2 = abs(texcoord.y - angle);
		angle2 *= 10.0;
		if (angle2 > 1.0)
		{
			angle2 = 1.0;
		}
			
		float multiply = 1.2*angle2*fadeOut*GetHeight();
		
		float distance = GetLinearDepth(texcoord);
		if (distance > 0.7) {}
		else if (distance > 0.4)
		{
			distance -= 0.4;
			distance *= 10.0/3.0;
			multiply *= distance;
		}
		else
		{
			multiply = 0.0;
		}
		color *= multiply;
		color += tex2D(SamplerBlur0, texcoord)*(1.0-multiply); 
	}
	else
	{
		color = tex2D(SamplerBlur0, texcoord);
	}
}

void PS_Refraction(float4 vpos : SV_Position, float2 texcoord : TEXCOORD, out float4 res : SV_Target0)
{
	[flatten]
	if (!(texcoord.x < PixelSize.x && texcoord.y < PixelSize.y) && !(texcoord.x > 1.0-PixelSize.x && texcoord.y < PixelSize.y) && !(texcoord.x < PixelSize.x && texcoord.y > 1.0-PixelSize.y))
	{
		float fadeOut = ComputeFadeOutHeatHaze();
		float heatup = tex2D(SamplerHeatHaze, (texcoord * float2(BUFFER_WIDTH,BUFFER_HEIGHT) * 0.008)+float2(Timer.x*0.0001,Timer.x*0.0002)).g;
		float heatdown = -(tex2D(SamplerHeatHaze, (texcoord * float2(BUFFER_WIDTH,BUFFER_HEIGHT) * 0.008)+float2(Timer.x*0.0001,Timer.x*0.0002)).r);
			
		float offset = texcoord.y;
			
		float distance = GetLinearDepth(texcoord);
		float angle = GetCameraAngle();
		
		float angle2 = abs(texcoord.y - angle);
		angle2 *= 10.0;
		if (angle2 > 1.0)
		{
			angle2 = 1.0;
		}
		
		if (fadeOut > 0.0 && angle < texcoord.y && distance > 0.7)
		{
			offset += ((heatup+heatdown)*0.005*fadeOut*GetHeight() + BUFFER_RCP_WIDTH*3.0)*angle2;
		}
		else if (fadeOut > 0.0 && angle < texcoord.y && distance > 0.4)
		{
			distance -= 0.4;
			distance *= 10.0/3.0;
			offset += ((heatup+heatdown)*0.005*fadeOut*GetHeight() + BUFFER_RCP_WIDTH*3.0)*angle2*distance;
		}
		res = tex2D(SamplerBlur2, float2(texcoord.x, offset));
	}
	else
	{
		res = tex2D(SamplerColor, texcoord);
	}
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

technique HeatHaze < bool enabled = HeatHaze_Effect; toggle = 0x7A;>
{
	pass P0
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader  = PS_Blur0;
		RenderTarget0 = texBlur0;
	}
	pass P1
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader  = PS_Blur1;
		RenderTarget0 = texBlur1;
	}
	pass P2
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader  = PS_Blur2;
		RenderTarget0 = texBlur2;
	}
	pass P3
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader  = PS_Refraction;
	}
}


#pragma message "Heat Haze Effect by robi29\nfor VisualV\n"